package ru.spb.osll.myfit.wikiverifier.verifier;

import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import ru.spb.osll.myfit.common.Table;
import ru.spb.osll.myfit.common.TableCell;
import ru.spb.osll.myfit.util.StringUtils;
import ru.spb.osll.myfit.wikiverifier.result.TableVerificationResult;
import ru.spb.osll.myfit.wikiverifier.result.VerificationResultType;
import util.GracefulNamer;

public class SetUpFixtureVerifier extends BasicFixtureVerifier {
	private Map<String, Class<?>> m_fixtures;

	public SetUpFixtureVerifier(Map<String, Class<?>> fixtures) {
		m_fixtures = fixtures;
	}

	@Override
	public TableVerificationResult verifyTable(Table table) {
		Iterator<Vector<TableCell>> tableIter = table.getData().iterator();

		if (!tableIter.hasNext()) {
			return new TableVerificationResult(VerificationResultType.FAILURE,
					table, "Test table is empty");
		}

		String className = getClassName(tableIter.next());
		if (m_fixtures.containsKey(className + "Fixture")) {
			className = className + "Fixture";
		}

		if (!m_fixtures.containsKey(className)) {
			return new TableVerificationResult(VerificationResultType.FAILURE,
					table, "Fixture class " + className + " not found");
		}

		Class<?> fixtureClass = m_fixtures.get(className);

		if (!tableIter.hasNext()) {
			return new TableVerificationResult(VerificationResultType.FAILURE,
					table, "Column names are empty");
		}

		Vector<TableCell> setUpMethodLine = tableIter.next();
		if (!verifySetUpMethodLine(fixtureClass, setUpMethodLine)) {
			return new TableVerificationResult(VerificationResultType.FAILURE,
					table, "Method " + setUpMethodName(setUpMethodLine)
							+ " with " + setUpMethodLine.size()
							+ " parameters not found in class " + className);
		}

		int paramCount = setUpMethodLine.size();

		while (tableIter.hasNext()) {
			if (tableIter.next().size() != paramCount) {
				return new TableVerificationResult(VerificationResultType.FAILURE,
						table, "Row should have " + setUpMethodLine.size() + " cells");
			}
		}

		return new TableVerificationResult(VerificationResultType.OK);
	}

	private String setUpMethodName(Vector<TableCell> line) {
		return GracefulNamer.disgrace(StringUtils.join(line, " "));
	}

	private boolean verifySetUpMethodLine(Class<?> fixtureClass,
			Vector<TableCell> line) {
		Method method = findMethod(setUpMethodName(line), fixtureClass);

		if (method == null) {
			return false;
		}

		if (method.getParameterTypes().length != line.size()) {
			return false;
		}

		return true;
	}
}